package com.apes.fn.scm.settle.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.crm.customerExpand.FnCustomerExpand;
import com.apes.fn.crm.customerExpand.FnCustomerExpandRepository;
import com.apes.fn.scm.contract.FnContract;
import com.apes.fn.scm.contract.FnContractRepository;
import com.apes.fn.scm.settle.model.PlatformSettle;
import com.apes.fn.scm.settle.model.PlatformSettleItem;
import com.apes.fn.scm.settle.model.PlatformSettleItemSummary;
import com.apes.fn.scm.settle.model.PlatformSettleRebate;
import com.apes.fn.scm.settle.repository.PlatformSettleRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.generator.service.SequenceService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.outbox.OutboxEventService;
import com.apes.framework.plugin.outbox.OutboxPayloadWrapper;
import com.apes.framework.plugin.outbox.annotation.OutboxSubscriber;
import com.apes.framework.plugin.soe.metadata.BusinessAttributeValue;
import com.apes.framework.plugin.soe.metadata.BusinessType;
import com.apes.framework.plugin.soe.store.database.repository.BusinessTypeRepository;
import com.apes.framework.util.Arith;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apes.scm.account.account.model.Cooperation;
import com.apes.scm.account.account.repository.CooperationRepository;
import com.apes.scm.account.account.repository.InventoryBatchRepository;
import com.apes.scm.account.ledger.service.LedgerService;
import com.apes.scm.account.tax.model.Tax;
import com.apes.scm.account.tax.repository.TaxRepository;
import com.apes.scm.contract.model.Contract;
import com.apes.scm.contract.repository.ContractRepository;
import com.apes.scm.income.model.Income;
import com.apes.scm.income.model.IncomeItem;
import com.apes.scm.income.repository.IncomeRepository;
import com.apes.scm.invoice.model.Invoice;
import com.apes.scm.invoice.model.InvoiceItem;
import com.apes.scm.invoice.repository.InvoiceItemRepository;
import com.apes.scm.invoice.repository.InvoiceRepository;
import com.apes.scm.invoice.service.InvoiceService;
import com.apes.scm.masterdata.finance.model.PaymentMethodType;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.masterdata.product.model.Product;
import com.apes.scm.masterdata.product.repository.ProductRepository;
import com.apes.scm.settle.payment.model.*;
import com.apes.scm.settle.payment.repository.PaymentExecuteRecordRepository;
import com.apes.scm.settle.payment.service.PaymentExecuteRecordService;
import com.apes.scm.settle.payment.service.PaymentService;
import com.apes.scm.settle.settle.model.*;
import com.apes.scm.settle.settle.respository.SettleRepository;
import com.apes.scm.settle.settle.respository.TaxBillRepository;
import com.apestech.framework.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.validation.constraints.NotNull;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;


/**
 * @BelongsProject: apes-server
 * @BelongsPackage: com.apes.fn.scm.settle.service
 * @ClassName: PlatformSettleService
 * @Author: pyb
 * @CreateTime: 2020-02-28 10:45
 * @Description: 平台供货结算服务
 * @Version: 1.0
 */
@Service("platformSettleService")
public class PlatformSettleService extends DomainService {
    PlatformSettleRepository platformSettleRepository;

    @Autowired
    private void setPlatformSettleRepository(PlatformSettleRepository platformSettleRepository) {
        this.platformSettleRepository = platformSettleRepository;
    }

    @Autowired
    private LedgerService ledgerService;

    @Autowired
    private SettleRepository settleRepository;

    @Autowired
    private InvoiceService invoiceService;

    @Autowired
    private InvoiceItemRepository invoiceItemRepository;

    @Autowired
    private ContractRepository contractRepository;

    @Autowired
    private InvoiceRepository invoiceRepository;

    @Autowired
    private FnContractRepository fnContractRepository;

    @Autowired
    private BusinessTypeRepository businessTypeRepository;

    @Autowired
    private IncomeRepository incomeRepository;

    @Autowired
    private FnCustomerExpandRepository fnCustomerExpandRepository;

    @Autowired
    private DeptRepository deptRepository;

    @Autowired
    private ProductRepository productRepository;

    @Autowired
    private TaxRepository taxRepository;

    @Autowired
    private PartyRoleRepository partyRoleRepository;

    @Autowired
    private PlatformSettleDao platformSettleDao;

    @Autowired
    private TaxBillRepository taxBillRepository;

    public void OutboxPayloadWrapper (Contract contract){
        OutboxPayloadWrapper wrapper = new OutboxPayloadWrapper();
        wrapper.setSubscriber("local:supplierPlatformSettle.createPlatform");
        wrapper.setPayload(JSON.toJSONString(MapUtil.mapper("contractId",contract.getId())));
        wrapper.setAggregateId(contract.getId());
        SpringManager.getBean(OutboxEventService.class).sendSaveEvent(wrapper);
    }

    @OutboxSubscriber(id="local:supplierPlatformSettle.createPlatform", name="定时任务生成供应商对账单")
    public void createSupplierPlatform(OutboxPayloadWrapper outboxPayloadWrapper){
        Contract contract = contractRepository.findOne(JSONObject.parseObject(outboxPayloadWrapper.getPayload()).getString("contractId"));
        //查询供应商账单
        Map<String, Object> invoiceMap = findInvoice(contract);
        if(invoiceMap == null) return;
        //生成供应商对账单
        createPlatformSettle(contract, invoiceMap);
    }

    public void createSupplierPlatform(PlatformSettle platformSettle,String stateType){
        JSONObject invoke = JSONObject.parseObject(this.invoke("supplierPlatformSettle.createSupplierPlatform",
                MapUtil.mapped(MapUtil.mapper("id", platformSettle.getId(), "supplier", platformSettle.getSupplier(),
                        "paymentMonth", platformSettle.getPaymentMonth(), "dateApprove", platformSettle.getDateApprove(),"version",platformSettle.getVersion() == 0 ? platformSettle.getVersion():platformSettle.getVersion() - 1,
                        "datePayment", platformSettle.getDatePayment(), "reconcileBeginDate", platformSettle.getReconcileBeginDate(), "reconcileEndDate", platformSettle.getReconcileEndDate(),
                        "note", platformSettle.getNote(), "reason", platformSettle.getReason(), "state", platformSettle.getState(), "type", platformSettle.getType(), "stateType",stateType))
        ));
        if(invoke.containsKey("body")) throw new RuntimeException("保存供应商平台失败" + invoke.getJSONObject("header").getString("message"));
    }

    public PlatformSettle save(SimpleRequest request) {
        PlatformSettle platformSettle = request.getO(PlatformSettle.class);
        if (!platformSettle.getReconcileBeginDate().before(new Date())) {
            throw new RuntimeException("开始对账日期 不能在当前日期之前");
        }
        //冻结账单明细
        invoiceFreeze(platformSettle, 1);
        platformSettle.setReconcileUid(getPerson(request));
        platformSettle.setCreator(request.getPersonId());
        platformSettle.computeAmt();
        platformSettle = platformSettleRepository.saveAndFlush(platformSettle);
        //状态同步到供应商平台触发状态流
        createSupplierPlatform(platformSettle,"sent");
        return platformSettle;
    }

    public PlatformSettle update(SimpleRequest request) {
        PlatformSettle platformSettle = request.getO(PlatformSettle.class);
        //还原原账单冻结明细
        invoiceFreeze(platformSettleRepository.findOne(platformSettle.getId()), -1);
        //冻结账单明细
        invoiceFreeze(platformSettle, 1);
        platformSettle.setReconcileUid(getPerson(request));
        platformSettle.computeAmt();
        //状态同步到供应商平台触发状态流
        platformSettle = platformSettleRepository.saveAndFlush(platformSettle);
        createSupplierPlatform(platformSettle,"update");
        return platformSettle;
    }

    /**
     * 审核
     *
     * @param request
     * @return
     */
    public PlatformSettle approval(SimpleRequest request) {
        PlatformSettle platformSettle = request.getO(PlatformSettle.class);
        platformSettle.setState("approve");
        platformSettle.setApproveUid(getPerson(request));
        platformSettle.setDateApprove(new Date());
        //状态同步到供应商平台触发状态流
        platformSettle = platformSettleRepository.saveAndFlush(platformSettle);
        createSupplierPlatform(platformSettle,"approve");
        return platformSettle;
    }

    /**
     * 退回
     *
     * @param request
     * @return
     */
    public PlatformSettle settleReturn(SimpleRequest request){
        //获取供应商操作日志
        JSONObject user = request.getJO().getJSONObject("user");
        PlatformSettle platformSettle = request.getO(PlatformSettle.class);
        platformSettle.setState("sent");
        if(platformSettle.getReason() == null || platformSettle.getReason().isEmpty()) throw new RuntimeException("请填写退回原因");
        platformSettle = platformSettleRepository.saveAndFlush(platformSettle);
        //状态同步到供应商平台触发状态流
        createSupplierPlatform(platformSettle,"return");
        if(user != null){
            platformSettle.setUserId(user.getString("id"));
            platformSettle.setUserName(user.getString("name"));
        }
        return platformSettle;
    }

    /**
     * 删除
     *
     * @param request
     * @return
     */
    public String delete(SimpleRequest request) {
        PlatformSettle o = request.getO(PlatformSettle.class);
        //还原冻结账单明细
        invoiceFreeze(o, -1);
        platformSettleRepository.delete(o);
        return "删除成功";
    }

    /**
     * 确认
     *
     * @param request
     * @return
     */
    public PlatformSettle payment(SimpleRequest request) {
        PlatformSettle platformSettle = request.getO(PlatformSettle.class);
        JSONObject user = request.getJO().getJSONObject("user");
        platformSettle.setDateApprove(new Date());
        platformSettle.setState("payment");
        platformSettle.setPaymentUid(getPerson(request));
        platformSettle.setDatePayment(new Date());
        //生成采购结算单前先还原冻结账单明细
        invoiceFreeze(platformSettle, -1);
        //单独冻结费用账单明细
        platformSettle.getPlatformSettleCosts().forEach(settleCost -> {
            IncomeItem incomeItem = settleCost.getIncomeItem();
            // 增加收入单冻结金额,更新是否完成
            incomeItem.changeFreezeAmount(settleCost.getActualAmount() * 1);
            incomeItem.updateDone();
        });
        //业务公司对供应商生成结算单
        settleCreate(platformSettle.getId());
        //只有协议生成
        if("protocol".equals(platformSettle.getType())){
            paymentRegisterCreate(platformSettle.getId());
            generateBySupplier(platformSettle.getId());
            platformSettle.setState("already");
            platformSettle.setInvoicedAmount(platformSettle.getPayableAmt());
        }
        PlatformSettle saveAndFlush = platformSettleRepository.saveAndFlush(platformSettle);
        //状态同步到供应商平台触发状态流
        createSupplierPlatform(saveAndFlush,"payment");
        if(user != null){
            saveAndFlush.setUserId(user.getString("id"));
            saveAndFlush.setUserName(user.getString("name"));
        }
        return saveAndFlush;
    }

    public void settleCreate (String platformSettleId){
        OutboxPayloadWrapper wrapper = new OutboxPayloadWrapper();
        wrapper.setSubscriber("local:platformSettleService.settleCreate");
        wrapper.setPayload(JSON.toJSONString(MapUtil.mapper("platformSettleId",platformSettleId)));
        wrapper.setAggregateId(platformSettleId);
        SpringManager.getBean(OutboxEventService.class).sendSaveEvent(wrapper);
    }

    @OutboxSubscriber(id="local:platformSettleService.settleCreate", name="对账单生成结算单")
    public void settleCreate(OutboxPayloadWrapper outboxPayloadWrapper){
        PlatformSettle platformSettle = platformSettleRepository.findOne(JSONObject.parseObject(outboxPayloadWrapper.getPayload()).getString("platformSettleId"));
        settleCreate(platformSettle);
    }

    private void settleCreate(PlatformSettle platformSettle){
        //根据公司分组
        Map<PartyRole, List<PlatformSettleItem>> partyRoleListMap = platformSettle.getPlatformSettleItems().stream().collect(Collectors.groupingBy(PlatformSettleItem::getCompany));
        Map<@NotNull PartyRole, List<PlatformSettleRebate>> rebateMap = platformSettle.getPlatformSettleRebates().stream().collect(Collectors.groupingBy(rebates ->
                rebates.getIncomeItem().getIncome().getCompany()
        ));
        partyRoleListMap.forEach((k, v) -> v.stream().collect(Collectors.groupingBy(p->p.getInvoiceItem().getInvoice().getInventoryMode())).forEach((inventoryMode, i)->{
            //转成采购结算单
            //主表信息
            Settle settle = new Settle();
            settle.setCompany(k);
            Dept dept = SpringManager.getBean(DeptRepository.class).findAll(JpaDsl.toCriteriaByEq("company.id", k.getId(),
                    "deptType.id", "000006"
            )).stream().findFirst().orElseThrow(() -> new RuntimeException(String.format("公司[%s]找不到对应的采购部门！无法产生采购结算！", k.getName())));
            Cooperation cooperation = SpringManager.getBean(CooperationRepository.class).findOne(JpaDsl.toCriteriaByEq("inventoryMode", inventoryMode)).get();
            settle.setDept(dept);
            settle.setOrigin(platformSettle.getId());
            settle.setOriginBusinessName("PlatformSettle");

            settle.setPartner(platformSettle.getSupplier());
            settle.setCooperation(cooperation);
            List<SettleItem> items = new ArrayList<>();
            List<SettleRebate> settleRebates = new ArrayList<>();
            //业务明细
            i.forEach(item -> conversionSettleDetails(item, items));
            //返利明细
            if (rebateMap.get(k) != null) rebateMap.get(k).stream().filter(rebate->Objects.equals(cooperation.getId(),rebate.getIncomeItem().getIncome().getCooperation().getId())).forEach(rebate -> conversionRebateDetails(rebate, settleRebates));
            settle.setSettleRebates(settleRebates);
            settle.setSettleItems(items);
            //生成采购结算单
            Map mapped = MapUtil.mapped(settle);
            mapped.put("items", MapUtil.mapped(settle.getSettleItems()));
            Settle invoke = invoke("settle.create", mapped);
            //审核采购结算单
            Map map = MapUtil.mapped(invoke);
            //只有协议生成
            if("protocol".equals(platformSettle.getType())){
                TaxBill taxBill = new TaxBill();
                Set<TaxBillItem> taxBillItems = new HashSet<>();
                TaxBillItem taxBillItem = new TaxBillItem();
                BusinessAttributeValue businessAttributeValue = new BusinessAttributeValue();
                businessAttributeValue.setId("TaxBillItem.type.not");
                businessAttributeValue.setName("无发票");
                businessAttributeValue.setCode("not");
                taxBillItem.setType(businessAttributeValue);
                taxBillItem.setCode("-");
                taxBillItem.setAmount(invoke.getSettleAmount());
                taxBillItem.setRebateAmount(invoke.getRebateAmount());
                taxBillItem.setTaxAmount(invoke.getSettleTax());
                taxBillItem.setTaxReturnDate(new Date());
                taxBillItems.add(taxBillItem);

                taxBill.getTaxBillItems().clear();
                taxBill.setTaxBillItems(taxBillItems);
                taxBill.setOrigin(platformSettle.getId());
                taxBill.setOriginBusinessName("PlatformSettle");
                taxBill.setCreator("system");
                Map taxMap = MapUtil.mapped(taxBill);
                map.put("taxBill", taxMap);
                Object o = invoke("settle.approveControls", map);
                //执行
                invoke("settle.executive", MapUtil.mapped(o));
            } else {
                Object o = invoke("settle.approve", map);
                invoke("settle.executive", MapUtil.mapped(o));
            }
        }));
    }

    public void paymentRegisterCreate (String platformSettleId){
        OutboxPayloadWrapper wrapper = new OutboxPayloadWrapper();
        wrapper.setSubscriber("local:platformSettleService.paymentRegisterCreate");
        wrapper.setPayload(JSON.toJSONString(MapUtil.mapper("platformSettleId",platformSettleId)));
        wrapper.setAggregateId(platformSettleId);
        SpringManager.getBean(OutboxEventService.class).sendSaveEvent(wrapper);
    }

    @OutboxSubscriber(id="local:platformSettleService.paymentRegisterCreate", name="对账单生成付款登记单")
    public void paymentRegisterCreate(OutboxPayloadWrapper outboxPayloadWrapper){
        PlatformSettle platformSettle = platformSettleRepository.findOne(JSONObject.parseObject(outboxPayloadWrapper.getPayload()).getString("platformSettleId"));
        paymentRegisterCreate(platformSettle);
    }

    private void paymentRegisterCreate(PlatformSettle platformSettle){
        //根据公司分组
        Map<PartyRole, List<PlatformSettleItem>> partyRoleListMap = platformSettle.getPlatformSettleItems().stream().collect(Collectors.groupingBy(PlatformSettleItem::getCompany));
        partyRoleListMap.forEach((k, v) -> v.stream().collect(Collectors.groupingBy(platformSettleItem -> platformSettleItem.getInvoiceItem().getInvoice().getInventoryMode())).forEach((inventoryMode, platformSettleItems) -> {
            Settle purSettle = SpringManager.getBean(SettleRepository.class).findOne(JpaDsl.toCriteriaByEq(
                    "origin", platformSettle.getId(), "originBusinessName", "PlatformSettle", "company.id", k.getId(), "partner.id", platformSettle.getSupplier().getId(), "cooperation.inventoryMode",inventoryMode )
            ).orElseThrow(() -> new RuntimeException("未找到对应的采购结算单"));
            PaymentRegister register = new PaymentRegister();
            register.setCompany(k);
            Dept dept = SpringManager.getBean(DeptRepository.class).findAll(JpaDsl.toCriteriaByEq("company.id", k.getId(),
                    "deptType.id", "000006"
            )).stream().findFirst().orElseThrow(() -> new RuntimeException(String.format("公司[%s]找不到对应的采购部门！无法产生采购付款！", k.getName())));
            PartyRole partyRole = partyRoleRepository.findOne("system");
            register.setCreator("system");
            register.setApproveUID(partyRole);
            register.setDept(dept);
            register.setPartner(platformSettle.getSupplier());

            register.setCooperation(purSettle.getCooperation());
            Set<PaymentRegisterItem> paymentRegisterItem = new HashSet<>();
            if (purSettle.getSettleAmount() != 0) {
                //Set<TaxBillItem> billItems = purSettle.getTaxBill().getTaxBillItems();
                List<TaxBill> taxBills = taxBillRepository.findAll(JpaDsl.toCriteriaByEq("settle.id", purSettle.getId()));
                if (!CollectionUtils.isEmpty(taxBills)){
                    taxBills.forEach(taxBill -> {
                        Set<TaxBillItem> billItems = taxBill.getTaxBillItems();
                        billItems.forEach(taxBillItem -> {
                            PaymentRegisterItem item = new PaymentRegisterItem();
                            item.setTaxBillItem(taxBillItem);
                            item.setAmount(taxBillItem.getAmount() - taxBillItem.getActualAmount() - taxBillItem.getFreezeAmount());
                            item.setPayableAmount(taxBillItem.getAmount() - taxBillItem.getActualAmount() - taxBillItem.getFreezeAmount());
                            item.setOrigin(platformSettle.getId());
                            item.setOriginBusinessType(platformSettle.getInnerBusinessType());
                            paymentRegisterItem.add(item);
                        });
                    });
                }

                register.getPaymentRegisterItem().clear();
                register.setPaymentRegisterItem(paymentRegisterItem);
                Map mapped = MapUtil.mapped(register);
                //创建付款登记表 并审核
                this.invoke("paymentRegister.approve", MapUtil.mapped(invoke("paymentRegister.create", mapped)));
                //根据公司和合作伙伴查询执行记录
                List<PaymentExecuteRecord> payment = SpringManager.getBean(PaymentExecuteRecordRepository.class).findAllForPayment(k.getId(), platformSettle.getSupplier().getId());
                payment.forEach(e -> {
                    if (e.getDept().getId().equals(dept.getId())) {
                        SimpleRequest request = new SimpleRequest();
                        //收付款执行记录自动生成付款单接口
                        request.setData(null);
                        request.setData(MapUtil.mapped(e));
                        Payment flowPayment = SpringManager.getBean(PaymentExecuteRecordService.class).flowPayment(request);
                        flowPayment.setCreator("system");
                        flowPayment.setApproveUID(partyRole);
                        //付款明细
                        Set<PaymentMethod> paymentMethodSet = new HashSet<>();

                        PaymentMethod paymentMethod = new PaymentMethod();
                        paymentMethod.setAmount(e.getAmount());
                        PaymentMethodType paymentMethodTyp = new PaymentMethodType();
                        paymentMethodTyp.setId("001");
                        paymentMethod.setPaymentMethodType(paymentMethodTyp);
                        paymentMethodSet.add(paymentMethod);
                        flowPayment.getPaymentMethodSet().clear();
                        flowPayment.setPaymentMethodSet(paymentMethodSet);
                        Map map = MapUtil.mapped(flowPayment);
                        request.setData(null);
                        request.setData(map);
                        this.invoke("payment.approve", MapUtil.mapped(SpringManager.getBean(PaymentService.class).create(request)));
                    }
                });
            }
        }));
    }

    public void generateBySupplier (String platformSettleId){
        OutboxPayloadWrapper wrapper = new OutboxPayloadWrapper();
        wrapper.setSubscriber("local:platformSettleService.generateBySupplier");
        wrapper.setPayload(JSON.toJSONString(MapUtil.mapper("platformSettleId",platformSettleId)));
        wrapper.setAggregateId(platformSettleId);
        SpringManager.getBean(OutboxEventService.class).sendSaveEvent(wrapper);
    }

    @OutboxSubscriber(id="local:platformSettleService.generateBySupplier", name="生成平台对供应商的结算和付款登记单")
    public void generateBySupplier(OutboxPayloadWrapper outboxPayloadWrapper){
        PlatformSettle platformSettle = platformSettleRepository.findOne(JSONObject.parseObject(outboxPayloadWrapper.getPayload()).getString("platformSettleId"));
        generateBySupplier(platformSettle);
    }

    private void generateBySupplier(PlatformSettle platformSettle){
        //生成平台对供应商的结算
        generatePlatformSettlement(platformSettle);
        //生成平台对供应商的付款登记
        generatePlatformPaymentRegister(platformSettle);
    }

    /**
     * 冻结账单
     * @param platformSettle
     * @param flag
     */
    private void invoiceFreeze(PlatformSettle platformSettle, int flag) {
        //冻结账单明细
        platformSettle.getPlatformSettleItems().forEach(item -> invoiceService.addInvoiceItemFreezeQty(item.getInvoiceItem(), item.getActualQty() * flag));
        //冻结返利账单明细
        platformSettle.getPlatformSettleRebates().forEach(settleRebate -> {
            IncomeItem incomeItem = settleRebate.getIncomeItem();
            // 增加收入单冻结金额,更新是否完成
            incomeItem.changeFreezeAmount(settleRebate.getActualAmount() * flag);
            incomeItem.updateDone();
        });
        //冻结费用账单明细
        platformSettle.getPlatformSettleCosts().forEach(settleCost -> {
            IncomeItem incomeItem = settleCost.getIncomeItem();
            // 增加收入单冻结金额,更新是否完成
            incomeItem.changeFreezeAmount(settleCost.getActualAmount() * flag);
            incomeItem.updateDone();
        });
    }


    /**
     * 统计
     *
     * @param request
     * @return
     */
    public Map statistics(SimpleRequest request) {
        JSONObject requestJO = request.getJO();
        String companyId = requestJO.getString("companyId");
        String supplierId = requestJO.getString("supplierId");
        String cooperationId = requestJO.getString("cooperationId");
        Date reconcileBeginDate = new Date();
        Date reconcileEndDate = new Date();
        try {
            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            reconcileBeginDate = dateFormat.parse(requestJO.getString("reconcileBeginDate"));
            reconcileEndDate = dateFormat.parse(requestJO.getString("reconcileEndDate"));
        } catch (ParseException e) {
            // ... handle parsing exception
        }
        List<String> companyList = new ArrayList<>();
        //通过公司和结算期止找赋能合同
        List<FnContract> fnContracts = fnContractRepository.findByCompany(companyId,reconcileEndDate);
        Map result = new HashMap();
        //没有赋能合同就为采购合同
        if(fnContracts.isEmpty()){
            companyList.add(companyId);
            result.put("type","contract");
        } else {
            //协议
            fnContracts.forEach(fnContract -> companyList.add(fnContract.getPartner().getId()));
            result.put("type","protocol");
        }
        List<Map<String, Object>> invoiceItemsByCompanyIdAndDept = invoiceItemRepository.findInvoiceItemsByPartnerIdAndPlat(companyList,supplierId, false, reconcileBeginDate, getEndOfDay(reconcileEndDate),"distribution".equals(cooperationId)?"IM_OWN":"IM_CONSIGN");
        //获取总账
        Map ledger = ledgerService.summary(MapUtil.mapper("company.id",companyId,"partner.id", supplierId));

        result.put("inventoryAmount", SpringManager.getBean(InventoryBatchRepository.class).findStandingInventoryAmount(supplierId, "consignment"));
        result.put("prepaidBalance", ledger.get("prepayment_unsettled") == null ? 0.0 : ledger.get("prepayment_unsettled"));
        result.put("content", invoiceItemsByCompanyIdAndDept);
        result.put("reconcileBeginDate", DateUtil.format(reconcileBeginDate, DateUtil.SHOW_DATE_FORMAT));
        result.put("reconcileEndDate", DateUtil.format(reconcileEndDate, DateUtil.SHOW_DATE_FORMAT));
        result.put("paymentMonth", DateUtil.format(reconcileBeginDate, DateUtil.SHOW_MONTH_FORMAT));
        return result;
    }

//    public Map getPlatformSettleItemSummaryList(SimpleRequest request){
//        List<Object> lists = request.get("platformSettleItems");
//        List<PlatformSettleItem> platformSettleItems = new ArrayList<>();
//        lists.forEach(list -> platformSettleItems.add(MapUtil.getO(list, PlatformSettleItem.class)));
//        return MapUtil.mapper("content",createPlatformSettleItemSummary(platformSettleItems));
//    }

    public Map getPlatformSettleItemSummaryList(SimpleRequest request){
        List<JSONObject> lists = request.get("platformSettleItems");
        List<PlatformSettleItemSummary> platformSettleItemSummaryList = new ArrayList<>();
        //通过商品分组后再通过价格分组
        Map<String, Map<Double, List<JSONObject>>> collect = lists.stream()
                .collect(Collectors.groupingBy(list -> list.getJSONObject("product").getString("id"), Collectors.groupingBy(list -> list.getDouble("priceUnit"))));
        collect.forEach((id, jsonObjectMap) ->
                jsonObjectMap.forEach((priceUnit, jsonObjectList) -> {
                    PlatformSettleItemSummary platformSettleItemSummary = new PlatformSettleItemSummary();
                    //商品
                    Product product = productRepository.findOne(id);
                    platformSettleItemSummary.setProduct(product);
                   //商品品类
                    platformSettleItemSummary.setClassify(product.getClassify());
                    //单价
                    platformSettleItemSummary.setPriceUnit(priceUnit);
                    //结算数量
                    Double actualQty = jsonObjectList.stream().mapToDouble(jsonObject -> jsonObject.getDouble("actualQty")).sum();
                    platformSettleItemSummary.setActualQty(actualQty);
                    //税金
                    platformSettleItemSummary.setAmtTax(jsonObjectList.stream().mapToDouble(jsonObject -> invoiceItemRepository.findOne(jsonObject.getJSONObject("invoiceItem").getLong("id")).getAmtTax()).sum());
                    //金额
                    platformSettleItemSummary.setAmount(jsonObjectList.stream().mapToDouble(jsonObject -> jsonObject.getDouble("amount")).sum());
                    //折扣金额
                    platformSettleItemSummary.setDiscountAmount(jsonObjectList.stream().mapToDouble(jsonObject -> jsonObject.getDouble("discountAmount")).sum());
                    //实结金额
                    Double actualSettlementAmount = jsonObjectList.stream().mapToDouble(jsonObject -> jsonObject.getDouble("floorPrice") * jsonObject.getDouble("actualQty")).sum();
                    platformSettleItemSummary.setActualSettlementAmount(actualSettlementAmount);
                    //实结单价
                    if(actualQty != 0) platformSettleItemSummary.setActualPriceUnit(Arith.round(actualSettlementAmount / actualQty,2));
                    //税率
                    Tax tax = taxRepository.findOne(jsonObjectList.get(0).getLong("taxId"));
                    platformSettleItemSummary.setTax(tax);
                    //实结税金
                    platformSettleItemSummary.setActualAmtTax(Arith.round(actualSettlementAmount - actualSettlementAmount / (1+ tax.obtainPercentTypeTax()),2));
            platformSettleItemSummaryList.add(platformSettleItemSummary);
        }));
        return MapUtil.mapper("content",platformSettleItemSummaryList);
    }


    public static LocalDate asLocalDate(Date date) {
        return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
    }

    public static Date getEndOfDay(Date date) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()),
                ZoneId.systemDefault());
        LocalDateTime endOfDay = localDateTime.with(LocalTime.MAX);
        return Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant());
    }


    @OutboxSubscriber(id = "local:platform.settle.approval", name = "平台供货结算审核（按公司）")
    private void approvalOutbox(OutboxPayloadWrapper outboxPayloadWrapper) {
        JSONObject jo = JSONObject.parseObject(outboxPayloadWrapper.getPayload());
        String settleId = jo.getString("settleId");
        String companyId = jo.getString("companyId");
        PartyRole company = SpringManager.getBean(PartyRoleRepository.class).findOne(companyId);
        PlatformSettle platformSettle = platformSettleRepository.findOne(settleId);
        Map<String, List<PlatformSettleRebate>> rebates = platformSettle.getPlatformSettleRebates().stream().filter(rebate -> rebate.getCompany().equals(company))
                .collect(Collectors.groupingBy(rebate -> rebate.getIncomeItem().getIncome().getCooperation().getInventoryMode()));
        platformSettle.getPlatformSettleItems().stream().filter(item -> item.getCompany().equals(company))
                .collect(Collectors.groupingBy(p -> p.getInvoiceItem().getInvoice().getInventoryMode()))
                .forEach((inventoryMode, settleItems) -> {

                    //生成采购结算单前先还原冻结账单明细
                    //冻结账单明细
                    platformSettle.getPlatformSettleItems().stream()
                            .filter(item -> item.getCompany().equals(company))
                            .forEach(item -> invoiceService.addInvoiceItemFreezeQty(item.getInvoiceItem(), -1 * item.getActualQty()));
                    //冻结返利账单明细
                    platformSettle.getPlatformSettleRebates().stream().filter(rebate -> rebate.getCompany().equals(company))
                            .forEach(settleRebate -> {
                                IncomeItem incomeItem = settleRebate.getIncomeItem();
                                // 增加收入单冻结金额,更新是否完成
                                incomeItem.changeFreezeAmount(-1 * settleRebate.getActualAmount());
                                incomeItem.updateDone();
                            });

                    //转成采购结算单
                    //主表信息
                    Settle settle = new Settle();
                    settle.setCompany(company);
                    Dept dept = SpringManager.getBean(DeptRepository.class).findAll(JpaDsl.toCriteriaByEq("company.id", company.getId(),
                            "deptType.id", "000006"
                    )).stream().findFirst().orElseThrow(() -> new RuntimeException(String.format("公司[%s]找不到对应的采购部门！无法产生采购结算！", company.getName())));
                    Cooperation cooperation = SpringManager.getBean(CooperationRepository.class).findOne(JpaDsl.toCriteriaByEq("inventoryMode", inventoryMode)).get();
                    settle.setDept(dept);
                    settle.setOrigin(platformSettle.getId());
                    settle.setOriginBusinessName("PlatformSettle");
                    settle.setPartner(platformSettle.getSupplier());
                    settle.setCooperation(cooperation);
                    List<SettleItem> items = new ArrayList<>();
                    List<SettleRebate> settleRebates = new ArrayList<>();
                    //业务明细
                    settleItems.forEach(item -> {
                        conversionSettleDetails(item, items);
                    });
                    //返利明细
                    if (rebates.get(inventoryMode) != null) {
                        rebates.get(inventoryMode).stream().forEach(rebate -> conversionRebateDetails(rebate, settleRebates));
                    }
                    settle.setSettleRebates(settleRebates);
                    settle.setSettleItems(items);
                    //生成采购结算单
                    Map mapped = MapUtil.mapped(settle);
                    mapped.put("items", MapUtil.mapped(settle.getSettleItems()));
                    Settle invoke = invoke("settle.create", mapped);
                    //审核采购结算单
                    Map map = MapUtil.mapped(invoke);
                    //税票登记
                    TaxBill taxBill = new TaxBill();
                    Set<TaxBillItem> taxBillItems = new HashSet<>();
                    TaxBillItem taxBillItem = new TaxBillItem();
                    BusinessAttributeValue businessAttributeValue = new BusinessAttributeValue();
                    businessAttributeValue.setId("TaxBillItem.type.not");
                    businessAttributeValue.setName("无发票");
                    businessAttributeValue.setCode("not");
                    taxBillItem.setType(businessAttributeValue);
                    taxBillItem.setCode("-");
                    taxBillItem.setAmount(invoke.getSettleAmount());
                    taxBillItem.setRebateAmount(invoke.getRebateAmount());
                    taxBillItem.setTaxAmount(invoke.getSettleTax());
                    taxBillItem.setTaxReturnDate(new Date());
                    taxBillItems.add(taxBillItem);

                    taxBill.getTaxBillItems().clear();
                    taxBill.setTaxBillItems(taxBillItems);
                    taxBill.setOrigin(platformSettle.getId());
                    taxBill.setOriginBusinessName("PlatformSettle");
                    taxBill.setCreator("system");
                    Map taxMap = MapUtil.mapped(taxBill);
                    map.put("taxBill", taxMap);
                    Object o = invoke("settle.approveControls", map);
                    //执行
                    invoke("settle.executive", MapUtil.mapped(o));
                });
    }

    @OutboxSubscriber(id = "local:platform.settle.payment", name = "平台供货结算付款（按公司）")
    private void paymentOutbox(OutboxPayloadWrapper outboxPayloadWrapper) {
        JSONObject jo = JSONObject.parseObject(outboxPayloadWrapper.getPayload());
        String settleId = jo.getString("settleId");
        String companyId = jo.getString("companyId");
        PartyRole company = SpringManager.getBean(PartyRoleRepository.class).findOne(companyId);
        PlatformSettle platformSettle = platformSettleRepository.findOne(settleId);
        platformSettle.getPlatformSettleItems().stream().filter(item -> item.getCompany().equals(company))
                .collect(Collectors.groupingBy(p -> p.getInvoiceItem().getInvoice().getInventoryMode()))
                .forEach((inventoryMode, settleItems) -> {
                    PaymentRegister register = new PaymentRegister();
                    register.setCompany(company);
                    Dept dept = SpringManager.getBean(DeptRepository.class).findAll(JpaDsl.toCriteriaByEq("company.id", company.getId(), "deptType.id", "000006"))
                            .stream().findFirst().orElseThrow(() -> new RuntimeException(String.format("公司[%s]找不到对应的采购部门！无法产生采购付款！", company.getName())));
                    register.setDept(dept);
                    register.setPartner(platformSettle.getSupplier());
                    Set<PaymentRegisterItem> paymentRegisterItem = new HashSet<>();
                    Settle purSettle = SpringManager.getBean(SettleRepository.class).findOne(JpaDsl.toCriteriaByEq(
                            "origin", settleId, "originBusinessName", "PlatformSettle", "company.id", company.getId(), "partner.id", platformSettle.getSupplier().getId(), "cooperation.inventoryMode", inventoryMode)
                    ).orElseThrow(() -> new RuntimeException("未找到对应的采购结算单"));
                    register.setCooperation(purSettle.getCooperation());
                    if (purSettle.getSettleAmount() != 0) {
                        //Set<TaxBillItem> billItems = purSettle.getTaxBill().getTaxBillItems();
                        List<TaxBill> taxBills = taxBillRepository.findAll(JpaDsl.toCriteriaByEq("settle.id", purSettle.getId()));
                        if (!CollectionUtils.isEmpty(taxBills)){
                            taxBills.forEach(taxBill -> {
                                Set<TaxBillItem> billItems = taxBill.getTaxBillItems();
                                billItems.forEach(taxBillItem -> {
                                    PaymentRegisterItem item = new PaymentRegisterItem();
                                    item.setTaxBillItem(taxBillItem);
                                    item.setAmount(taxBillItem.getAmount() - taxBillItem.getActualAmount() - taxBillItem.getFreezeAmount());
                                    item.setPayableAmount(taxBillItem.getAmount() - taxBillItem.getActualAmount() - taxBillItem.getFreezeAmount());
                                    item.setOrigin(platformSettle.getId());
                                    item.setOriginBusinessType(platformSettle.getInnerBusinessType());
                                    paymentRegisterItem.add(item);
                                });
                            });
                        }

                        register.getPaymentRegisterItem().clear();
                        register.setPaymentRegisterItem(paymentRegisterItem);
                        Map mapped = MapUtil.mapped(register);
                        //mapped.put("paymentRegisterItem", MapUtil.mapped(paymentRegisterItem));
                        //创建付款登记表 并审核
                        this.invoke("paymentRegister.approve", MapUtil.mapped(invoke("paymentRegister.create", mapped)));
                        //根据公司和合作伙伴查询执行记录
                        List<PaymentExecuteRecord> records = SpringManager.getBean(PaymentExecuteRecordRepository.class).findAllForPayment(company.getId(), platformSettle.getSupplier().getId());
                        records.forEach(record -> {
                            if (record.getDept().getId().equals(dept.getId())) {
                                //收付款执行记录自动生成付款单接口
                                Payment payment = invoke("paymentExecuteRecord.flow.payment", MapUtil.mapped(record));
                                //付款明细
                                Set<PaymentMethod> paymentMethodSet = new HashSet<>();
                                PaymentMethod paymentMethod = new PaymentMethod();
                                paymentMethod.setAmount(record.getAmount());
                                PaymentMethodType paymentMethodTyp = new PaymentMethodType();
                                paymentMethodTyp.setId("001");
                                paymentMethod.setPaymentMethodType(paymentMethodTyp);
                                paymentMethodSet.add(paymentMethod);
                                payment.getPaymentMethodSet().clear();
                                payment.setPaymentMethodSet(paymentMethodSet);
                                payment = invoke("payment.create", MapUtil.mapped(payment));
                                this.invoke("payment.approve", MapUtil.mapped(payment));
                            }
                        });
                    }
                });
    }

    /**
     * 生成平台对供应商的结算
     *
     * @param platformSettle
     */
    public void generatePlatformSettlement(PlatformSettle platformSettle) {
        if (!settleRepository.findAll(JpaDsl.toCriteriaByEq("company.id", "1007", "origin", platformSettle.getId(),
                "originBusinessName", platformSettle.getInnerBusinessType())).isEmpty()) {
            return;
        }

        //转成采购结算单
        //主表信息
        Settle settle = new Settle();
        //公司取车宝
        settle.setCompany(SpringManager.getBean(PartyRoleRepository.class).findById(platformSettle.getCompany().getId()).get());
        //部门取广州集群车宝采购中心
        Dept dept = deptRepository.findByDeptTypeIdAndCompanyId("000006",platformSettle.getCompany().getId());

        settle.setDept(dept);
        settle.setPartner(platformSettle.getSupplier());
        settle.setCooperation(platformSettle.getCooperation());
        settle.setOrigin(platformSettle.getId());
        settle.setOriginBusinessName("PlatformSettle");
        settle.setReceiptState("already");
        List<SettleItem> items = new ArrayList<>();
        List<SettleRebate> settleRebates = new ArrayList<>();
        platformSettle.getPlatformSettleItems().forEach(item -> conversionSettleDetails(item, items));
        //返利明细
        if (!platformSettle.getPlatformSettleRebates().isEmpty()) {
            platformSettle.getPlatformSettleRebates().forEach(rebate -> conversionRebateDetails(rebate, settleRebates));
        }
        settle.setSettleRebates(settleRebates);
        settle.setSettleItems(items);
        //增加账款未清项
        ledgerService.charge(settle.getCompany(), settle.getDept(), settle.getPartner(), settle.getCooperation().getInventoryMode(),
                settle.getCooperation().getAccountingMethod(), platformSettle.getId(), platformSettle.getClass().getSimpleName(), new Date(),
                "current_unsettled", platformSettle.getLoanAmt());
        //(去掉1007的返利)
        double rebatesAmount = settleRebates.stream().filter(settleRebate -> !Objects.equals("1007", settleRebate.getIncomeItem().getIncome().getCompany().getId()))
                .mapToDouble(SettleRebate::getActualAmount).sum();
        if (rebatesAmount > 0) {
            //增加返利未清项
            ledgerService.charge(settle.getCompany(), settle.getDept(), settle.getPartner(), settle.getCooperation().getInventoryMode(),
                    settle.getCooperation().getAccountingMethod(), platformSettle.getId(), platformSettle.getClass().getSimpleName(), new Date(),
                    "discount_unsettled", rebatesAmount);
        }
        //生成采购结算单
        settle = settleCreate(settle);

        //税票登记
        TaxBill taxBill = new TaxBill();
        Set<TaxBillItem> taxBillItems = new HashSet<>();
        TaxBillItem taxBillItem = new TaxBillItem();
        BusinessAttributeValue businessAttributeValue = new BusinessAttributeValue();
        businessAttributeValue.setId("TaxBillItem.type.not");
        businessAttributeValue.setName("无发票");
        businessAttributeValue.setCode("not");
        taxBillItem.setType(businessAttributeValue);
        taxBillItem.setCode(settle.getId());
        taxBillItem.setAmount(settle.getSettleAmount());
        taxBillItem.setRebateAmount(settle.getRebateAmount());
        taxBillItem.setTaxAmount(settle.getSettleTax());
        taxBillItem.setTaxReturnDate(new Date());
        taxBillItems.add(taxBillItem);

        taxBill.getTaxBillItems().clear();
        taxBill.setTaxBillItems(taxBillItems);
        taxBill.setPaymentMonth(platformSettle.getPaymentMonth());
        taxBill.setOrigin(platformSettle.getId());
        taxBill.setOriginBusinessName("PlatformSettle");
        taxBill.setCreator("system");
        //审核采购结算单
        Map map = MapUtil.mapped(settle);
        Map taxMap = MapUtil.mapped(taxBill);
        map.put("taxBill", taxMap);
        Settle appSettle = invoke("settle.approveControls", map);
        //执行
        executive(appSettle);
    }

    /**
     * 生成平台对供应商的付款登记
     *
     * @param platformSettle
     */
    public void generatePlatformPaymentRegister(PlatformSettle platformSettle) {
        PaymentRegister register = new PaymentRegister();
        //公司取车宝
        register.setCompany(SpringManager.getBean(PartyRoleRepository.class).findById(platformSettle.getCompany().getId()).get());
        register.setCreator("system");
        //广州市车宝网络赋能平台
        Dept dept = deptRepository.findByDeptTypeIdAndCompanyId("000006",platformSettle.getCompany().getId());
        register.setDept(dept);
        register.setPartner(platformSettle.getSupplier());
        register.setCooperation(platformSettle.getCooperation());
        Set<PaymentRegisterItem> paymentRegisterItem = new HashSet<>();
        Settle purSettle = SpringManager.getBean(SettleRepository.class).findOne(JpaDsl.toCriteriaByEq("origin", platformSettle.getId(), "originBusinessName", "PlatformSettle", "company.id", "1007", "partner.id", platformSettle.getSupplier().getId())).orElseThrow(() -> new RuntimeException("未找到对应的采购结算单"));
        if (purSettle.getSettleAmount() != 0) {
            //Set<TaxBillItem> billItems = purSettle.getTaxBill().getTaxBillItems();
            List<TaxBill> taxBills = taxBillRepository.findAll(JpaDsl.toCriteriaByEq("settle.id", purSettle.getId()));
            if (!CollectionUtils.isEmpty(taxBills)){
                taxBills.forEach(taxBill -> {
                    Set<TaxBillItem> billItems = taxBill.getTaxBillItems();
                    billItems.forEach(taxBillItem -> {
                        PaymentRegisterItem item = new PaymentRegisterItem();
                        item.setTaxBillItem(taxBillItem);
                        item.setAmount(taxBillItem.getAmount() - taxBillItem.getActualAmount() - taxBillItem.getFreezeAmount());
                        item.setPayableAmount(taxBillItem.getAmount() - taxBillItem.getActualAmount() - taxBillItem.getFreezeAmount());
                        item.setOrigin(platformSettle.getId());
                        item.setOriginBusinessType(platformSettle.getInnerBusinessType());
                        paymentRegisterItem.add(item);
                    });
                });
            }

            register.getPaymentRegisterItem().clear();
            register.setPaymentRegisterItem(paymentRegisterItem);
            Set<PaymentCost> paymentCostHashSet = new HashSet<>();
            platformSettle.getPlatformSettleCosts().forEach(platformSettleCost -> {
                PaymentCost paymentCost = new PaymentCost();
                paymentCost.setIncomeId(platformSettleCost.getIncomeId());
                paymentCost.setIncomeItemId(platformSettleCost.getIncomeItem());
                paymentCost.setPaymentCost(register);
                paymentCost.setInComeCategory(platformSettleCost.getInComeCategory());
                paymentCost.setIncomeType(platformSettleCost.getIncomeType());
                paymentCost.setIncomeAmount(platformSettleCost.getIncomeAmount());
                paymentCost.setAmount(platformSettleCost.getActualAmount());
                paymentCostHashSet.add(paymentCost);
            });
            register.setType("supplier");
            register.setPaymentIncomeSet(paymentCostHashSet);
            Map mapped = MapUtil.mapped(register);
            //创建付款登记表
            invoke("paymentRegister.createByPlatformSettle", mapped);
        }
    }

    /**
     * 转换返利明细
     *
     * @param rebate
     * @param settleRebates
     */
    private void conversionRebateDetails(PlatformSettleRebate rebate, List<SettleRebate> settleRebates) {
        SettleRebate settleRebate = new SettleRebate();
        settleRebate.setIncomeItem(rebate.getIncomeItem());
        settleRebate.setIncomeType(rebate.getIncomeType());
        settleRebate.setIncomeAmount(rebate.getIncomeAmount());
        settleRebate.setActualAmount(rebate.getActualAmount());
        settleRebate.setPendingAmount(rebate.getActualAmount());
        settleRebates.add(settleRebate);
    }

    /**
     * 转换结算明细
     *
     * @param item
     * @param items
     */
    private void conversionSettleDetails(PlatformSettleItem item, List<SettleItem> items) {
        SettleItem settleItem = new SettleItem();
        settleItem.setProduct(item.getProduct());
        settleItem.setUom(item.getUom());
        settleItem.setTax(item.getTax());
        settleItem.setInvoiceQty(item.getInvoiceItem().getQty());
        settleItem.setPendingQty(item.getActualQty());
        settleItem.setPriceUnit(item.getPriceUnit());
        settleItem.setActualQty(item.getActualQty());
        settleItem.setAmtTax(item.getInvoiceItem().getAmtTax());
        settleItem.setInvoiceItem(item.getInvoiceItem());
        settleItem.setOrigin(item.getOrigin());
        settleItem.setOriginBusinessType(item.getOriginBusinessType());
        settleItem.setOriginItemId(item.getInvoiceItem().getOriginItemId());
        String customerExpand = item.getInvoiceItem().getInvoice().getCustomerExpand();
        if(customerExpand != null)
            settleItem.setCarLicense(fnCustomerExpandRepository.findOne(customerExpand).getCarLicense());
        //将服务类型写入
        settleItem.setServeTypeId(item.getProduct().getServeType());
        settleItem.setSource(item.getInvoiceItem().getInvoice().getSource());
        settleItem.setSourceBusinessType(item.getInvoiceItem().getInvoice().getSourceBusinessType());
        items.add(settleItem);
    }

    /**
     * 重写一份生成采购结算单
     *
     * @param settle
     * @return
     */
    private Settle settleCreate(Settle settle) {
        String id = SpringManager.getBean(SequenceService.class).getId(Settle.CONST_TABLE_NAME);
        settle.setId(id);
        settle.setCreator(settle.getOperator());
        settle.setState("sent");
        // 初始化金额（明细重新结算）
        settle.initAmt();
        // 结算返利
        processSettleRebates(settle);
        // 结算明细
        processSettleItems(settle);

        Settle result = settleRepository.saveAndFlush(settle);
        // 账款项变化金额为： 结算 + 返利
        // 减少未清,增加冻结
        transaction(result, "current_unsettled", -1 * (result.getSettleAmount() + result.getRebateAmount()), "current_freeze", result.getSettleAmount() + result.getRebateAmount());
        // * 不能直接使用主表返利金额,明细折扣已经扣除返利
        // 存在使用返利明细
        double rebatesAmount = settle.getSettleRebates().stream().mapToDouble(SettleRebate::getActualAmount).sum();
        if (rebatesAmount > 0) {
            // 减少返利未清，增加返利冻结
            transaction(result, "discount_unsettled", -1 * rebatesAmount, "discount_freeze", rebatesAmount);
        }
        return result;
    }

    /**
     * 重写一份生成采购结算单
     *
     * @param settle
     * @return
     */
    public Settle executive(Settle settle) {
        settle.setState("executive");
        settle.setExecutiveDate(new Date());
        settle.setExecutiveUID(settle.getApproveUID());
        // 发票登记单写审核人、审核时间
        // 发票登记单写审核人、审核时间
        List<TaxBill> taxBills = taxBillRepository.findAll(JpaDsl.toCriteriaByEq("settle.id", settle.getId()));
        if (!CollectionUtils.isEmpty(taxBills)){
            taxBills.forEach(item -> {
                item.setApproveDate(new Date());
                item.setApproveUID(settle.getApproveUID());
                item.setState("approve");
                taxBillRepository.saveAndFlush(item);
            });
        }

        // 返利明细回写
        if(!settle.getSettleRebates().isEmpty()){
            settle.getSettleRebates().stream().filter(settleRebate -> Objects.equals("1007",settleRebate.getIncomeItem().getIncome().getCompany().getId())).forEach(
                    (settleRebate) -> {
                        IncomeItem incomeItem = settleRebate.getIncomeItem();
                        // 减少冻结金额
                        incomeItem.changeFreezeAmount(-1 * settleRebate.getActualAmount());
                        // 增加收款金额
                        incomeItem.changeRecoveryAmount(settleRebate.getActualAmount());
                    }
            );
        }
        // 这里为主表的返利金额
        if (!CollectionUtils.isEmpty(taxBills)) {
            taxBills.forEach(taxBill -> {
                if (!(taxBill.getRebateAmount() <= 0)) {
                    // 减少返利冻结，增加返利已清
                    transaction(taxBill, "discount_freeze", -1 * settle.getRebateAmount(), "discount_settled", settle.getRebateAmount());
                    // 减少冻结,增加已到票,增加已清项
                    transaction(taxBill, "current_freeze", -1 * Arith.add(taxBill.getAmtTotal(), taxBill.getRebateAmount()), "current_invoiced", taxBill.getAmtTotal(), "current_settled", taxBill.getRebateAmount());
                } else {
                    // 减少冻结,增加已到票
                    transaction(taxBill, "current_freeze", -1 * taxBill.getAmtTotal(), "current_invoiced", taxBill.getAmtTotal());
                }

                // 增加 invoice_unsettled 税票:未清项
                ledgerService.charge(taxBill.getCompany(), taxBill.getDept(), taxBill.getPartner(),
                        taxBill.getCooperation().getInventoryMode(), taxBill.getCooperation().getAccountingMethod(),
                        taxBill.getId(), taxBill.getInnerBusinessType(), new Date(), "invoice_unsettled", taxBill.getAmtTotal());
            });
        }
        return settleRepository.saveAndFlush(settle);
    }

    /**
     * 写入总账
     */
    private void transaction(Settle settle, Object... items) {
        ledgerService.transaction(settle.getCompany(), settle.getDept(), settle.getPartner(),
                settle.getCooperation().getInventoryMode(), settle.getCooperation().getAccountingMethod(),
                settle.getId(), settle.getInnerBusinessType(), new Date(), items);
    }

    /**
     * 写入总账
     */
    private void transaction(TaxBill taxBill, Object... items) {
        ledgerService.transaction(taxBill.getCompany(), taxBill.getDept(), taxBill.getPartner(),
                taxBill.getCooperation().getInventoryMode(), taxBill.getCooperation().getAccountingMethod(),
                taxBill.getId(), taxBill.getInnerBusinessType(), new Date(), items);
    }

    /**
     * 处理结算返利相关逻辑
     *
     * @param settle
     */
    private void processSettleRebates(Settle settle) {
        String id = settle.getId();
        // 结算返利
        List<SettleRebate> settleRebates = settle.getSettleRebates();
        SettleRebate settleRebate;
        IncomeItem incomeItem;
        int size = settleRebates.size();
        for (int i = 0; i < size; i++) {
            settleRebate = settleRebates.get(i);
            settleRebate.setId(new StringBuffer(id).append(".").append(i).toString());
            // 计算税金、更新主表返利金额
            settleRebate.computeAmt();
            if (Objects.equals("1007", settleRebate.getIncomeItem().getIncome().getCompany().getId())) {
                incomeItem = settleRebate.getIncomeItem();
                // 增加收入单冻结金额,更新是否完成
                incomeItem.changeFreezeAmount(settleRebate.getActualAmount());
                incomeItem.updateDone();
            }

        }
    }


    /**
     * 处理结算明细相关逻辑
     *
     * @param settle
     */
    private void processSettleItems(Settle settle) {
        String id = settle.getId();
        //结算明细数据过多,这里不取系统序列id
        List<SettleItem> settleItems = settle.getSettleItems();
        int size = settleItems.size();
        IntStream.range(0, size).forEach(
                (i) -> {
                    SettleItem item = settleItems.get(i);
                    String itemId = item.getId();
                    if (itemId == null) {
                        item.setId(new StringBuffer(id).append(".").append(i).toString());
                    }
                    // 重新计算入库、返厂、变价、返利、总计金额
                    item.computeAmt();

                }
        );
    }

    // 导入
    public Map importLogic(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        // 数据校验 判断前端明细是否有数据
        JSONObject modelJson = getJO.getJSONObject("model");
        if (modelJson.getJSONArray("items").isEmpty()) throw new RuntimeException("没有结算商品明细数据");

        // 数据匹配
        List list = builderResultList(modelJson.getJSONArray("items"), getJO.getJSONObject("importData"));

        return MapUtil.mapper("msg", "", "items", list);
    }

    private List<Map<String, Object>> builderResultList(JSONArray modelItems, JSONObject importData) {
        List<Map<String, Object>> resultList = new ArrayList<>();

        modelItems.forEach(modelItem -> {
            JSONObject itemJson = ((JSONObject) modelItem);
            String uniqueKey = itemJson.getString("source") + itemJson.getString("origin") + itemJson.getString("productId");

            importData.forEach((sheetName, excelItems) -> {
                JSONArray importDataValueArray = (JSONArray) excelItems;
                importDataValueArray.forEach(excelItem -> {
                    JSONArray iValueArray = (JSONArray) excelItem;
                    String importInvoiceItemId = iValueArray.get(0).toString();

                    if (Pattern.matches("[\\u4e00-\\u9fa5]*", importInvoiceItemId)) return;   // 匹 配中文
                    if (itemJson.getString("origin").equals(iValueArray.get(3)) && itemJson.getString("source").equals(iValueArray.get(5))
                            && itemJson.getInteger("pendingQty").equals(iValueArray.get(11))) {

                        // 如果导入的数据和SQL 查寻的数据一直就保留
                        resultList.add((Map) modelItem);
                    }
                });
            });
        });

        return resultList;
    }


    /**
     * 定时任务采购合同生成供应商对账单
     *
     * @param request
     */
    private void platformSettleByContract(SimpleRequest request){
        //获取有效的采购合同和协议,只找结算方式月结和半月结的
        List<Contract> contractList = contractRepository.findAllByState(new Date(), "approve");
        contractList.forEach(this::OutboxPayloadWrapper);
    }

    /**
     * 查询供应商账单
     *
     * @param contract
     * @return
     */
    public Map<String,Object> findInvoice(Contract contract){
        Map<String, Object> invoiceMap = new HashMap<>();
        //通过结算周期和结算类型获取时间范围
        Map<String, Date> dateMap = findDate(contract.getSettlementType().getCode());
        Date startDate = dateMap.get("startDate");
        Date endDate = dateMap.get("endDate");
        if(startDate == null || endDate == null) return null;
        List<Invoice> invoiceList = new ArrayList<>();
        //根据公司、合作伙伴、库存方式、结算周期找到所有的供应商账单
        if ("Contract.contractType.supplier".equals(contract.getContractType().getId())) {
            invoiceList = invoiceRepository.findBySupplierContract(contract.getCompany().getId(), contract.getPartner().getId(), contract.getCooperation().getInventoryMode(), startDate, endDate);
            invoiceMap.put("type","contract");
        } else if("Contract.contractType.platform".equals(contract.getContractType().getId())){
            invoiceList = invoiceRepository.findByPlatformContract(contract.getCompany().getId(), contract.getPartner().getId(), contract.getCooperation().getInventoryMode(), startDate, endDate);
            invoiceMap.put("type","protocol");
        }
        invoiceMap.put("invoiceList", invoiceList);
        invoiceMap.put("startDate", startDate);
        invoiceMap.put("endDate", endDate);
        return invoiceMap;
    }

    /**
     * 获取时间范围
     *
     * @param settlementType
     * @return
     */
    public Map<String,Date> findDate(String settlementType){
        Date startDate = null;
        Date endDate = null;
        //月结
        if ("month".equals(settlementType)) {
            Calendar calendar = Calendar.getInstance();
//            calendar.setTime(date);
            //只在日期为1号时进入
            if (calendar.get(Calendar.DATE) == 1) {
                //上月1号
                calendar.add(Calendar.MONTH, -1);
                startDate = calendar.getTime();
                //上月月末
                calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
                endDate = calendar.getTime();
            }
            //半月结
        } else if ("halfMonth".equals(settlementType)) {
            Calendar calendar = Calendar.getInstance();
//            calendar.setTime(date);
            //日期为1号生成上月16-月末
            if (calendar.get(Calendar.DATE) == 1) {
                calendar.add(Calendar.MONTH, -1);
                calendar.set(Calendar.DAY_OF_MONTH, 16);
                startDate = calendar.getTime();
                calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
                endDate = calendar.getTime();
                //日期为16号生成当月1-15号
            } else if (calendar.get(Calendar.DATE) == 16) {
                calendar.set(Calendar.DAY_OF_MONTH, 1);
                startDate = calendar.getTime();
                calendar.set(Calendar.DAY_OF_MONTH, 15);
                endDate = calendar.getTime();
            }
        }
        Map<String, Date> dateMap = new HashMap<>();
        dateMap.put("startDate", startDate);
        dateMap.put("endDate", endDate);
        return dateMap;
    }

    /**
     * 生成供应商对账单
     *
     * @param contract
     * @param invoiceMap
     */
    public void createPlatformSettle(Contract contract, Map<String, Object> invoiceMap) {
        PlatformSettle platformSettle = new PlatformSettle();
        List<Invoice> invoiceList = (List<Invoice>)invoiceMap.get("invoiceList");
        List<InvoiceItem> invoiceItemList = new ArrayList<>();
        invoiceList.forEach(invoice -> invoiceItemList.addAll(invoice.getInvoiceItems().stream().filter(invoiceItem -> !invoiceItem.isDone()).collect(Collectors.toList())));
        if(invoiceItemList.isEmpty()) return;
        //创建人
        platformSettle.setCreator("system");
        //公司
        platformSettle.setCompany(contract.getCompany());
        //供应商
        platformSettle.setSupplier(contract.getPartner());
        //部门
        platformSettle.setDept(contract.getDept());
        //合作方式
        platformSettle.setCooperation(contract.getCooperation());
        //货款月份
        platformSettle.setPaymentMonth(DateUtil.format((Date) invoiceMap.get("startDate"), DateUtil.SHOW_MONTH_FORMAT));
        //开始对账日期
        platformSettle.setReconcileBeginDate((Date) invoiceMap.get("startDate"));
        //结束对账日期
        platformSettle.setReconcileEndDate((Date) invoiceMap.get("endDate"));
        //返利金额
        platformSettle.setRebateAmt(0);
        //库存余额
        platformSettle.setInventoryAmount(SpringManager.getBean(InventoryBatchRepository.class).findStandingInventoryAmount(contract.getPartner().getId(), "consignment"));
        //预付余额
        Map<String, Double> ledger = ledgerService.summary(MapUtil.mapper("company", contract.getCompany(), "partner", contract.getPartner()));
        platformSettle.setPrepaidBalance(ledger.get("prepayment_unsettled") == null ? 0.0 : ledger.get("prepayment_unsettled"));
        //备注
        platformSettle.setNote("系统自动生成");
        //结算状态
        platformSettle.setState("sent");
        //合同类型
        platformSettle.setType(invoiceMap.get("type").toString());
        //生成供应商对账单明细
        List<PlatformSettleItem> platformSettleItems = createPlatformSettleItem(invoiceList,platformSettle);
        platformSettle.setPlatformSettleItems(platformSettleItems);
        //冻结账单明细
        invoiceFreeze(platformSettle,1);
        //生成供应商对账单明细汇总
        List<PlatformSettleItemSummary> platformSettleItemSummaryList = createPlatformSettleItemSummary(platformSettleItems);
        platformSettle.setPlatformSettleItemSummaryList(platformSettleItemSummaryList);
        //货款金额
        platformSettle.setLoanAmt(Arith.round(platformSettleItems.stream().mapToDouble(PlatformSettleItem::getAmount).sum(), 2));
        //结算金额
        platformSettle.setPayableAmt(Arith.round(platformSettle.getLoanAmt() - platformSettle.getRebateAmt(), 2));
        //合计折扣金额
        platformSettle.setDiscountAmount(platformSettleItems.stream().mapToDouble(PlatformSettleItem::getDiscountAmount).sum());
        platformSettle = platformSettleRepository.saveAndFlush(platformSettle);
//        //状态同步到供应商平台触发状态流
        createSupplierPlatform(platformSettle,"sent");
    }

    public List<PlatformSettleItem> createPlatformSettleItem(List<Invoice> invoiceList, PlatformSettle platformSettle) {
        List<PlatformSettleItem> platformSettleItems = new ArrayList<>();
        invoiceList.forEach(invoice -> invoice.getInvoiceItems().stream().filter(invoiceItem -> !invoiceItem.isDone()).forEach(invoiceItem -> {
            PlatformSettleItem platformSettleItem = new PlatformSettleItem();
            //结算单号
            platformSettleItem.setPlatformSettle(platformSettle);
            //商品
            platformSettleItem.setProduct(invoiceItem.getProduct());
            //赋能商户
            platformSettleItem.setCompany(invoice.getCompany());
            //结算数量
            platformSettleItem.setActualQty(invoiceItem.getQty() - invoiceItem.getFreezeQty() - invoiceItem.getSettledQty());
            //计量单位
            platformSettleItem.setUom(invoiceItem.getUom());
            //税率编码
            platformSettleItem.setTax(invoiceItem.getTax());
            //单价
            platformSettleItem.setPriceUnit(invoiceItem.getPriceUnit());
            //结算金额
            Map result = platformSettleItem.getTax().computeAll(platformSettle.getCompany(), platformSettleItem.getPriceUnit(), platformSettleItem.getActualQty());
            platformSettleItem.setAmount(((Double) result.get("totalIncluded")).doubleValue());
            //账单明细行号
            platformSettleItem.setInvoiceItem(invoiceItem);
            //来源单号
            platformSettleItem.setOrigin(invoice.getOrigin());
            //来源单类型
            platformSettleItem.setOriginBusinessType(invoice.getOriginBusinessType());
            //发生日期
            platformSettleItem.setOccurrenceDate(invoice.getCreateDate());
            //折扣金额
            platformSettleItem.setDiscountAmount(invoiceItem.getDiscount());
            //供应商低价
            platformSettleItem.setFloorPrice(invoiceItem.getFloorPrice());
            platformSettleItems.add(platformSettleItem);
        }));
        return platformSettleItems;
    }

    public List<PlatformSettleItemSummary> createPlatformSettleItemSummary(List<PlatformSettleItem> platformSettleItems) {
        List<PlatformSettleItemSummary> platformSettleItemSummaryList = new ArrayList<>();
        Map<Product, Map<Double, List<PlatformSettleItem>>> collect = platformSettleItems.stream().collect(Collectors.groupingBy(PlatformSettleItem::getProduct, Collectors.groupingBy(PlatformSettleItem::getPriceUnit)));
        collect.forEach((product, platformSettleItemMap) -> platformSettleItemMap.forEach((priceUnit, platformSettleItemList) -> {
            PlatformSettleItemSummary platformSettleItemSummary = new PlatformSettleItemSummary();
            //结算单号
            platformSettleItemSummary.setPlatformSettle(platformSettleItemList.get(0).getPlatformSettle());
            //商品
            platformSettleItemSummary.setProduct(product);
            //商品品类
            platformSettleItemSummary.setClassify(product.getClassify());
            //单价
            platformSettleItemSummary.setPriceUnit(priceUnit);
            //结算数量
            Double actualQty = platformSettleItemList.stream().mapToDouble(PlatformSettleItem::getActualQty).sum();
            platformSettleItemSummary.setActualQty(actualQty);
            //税金
            platformSettleItemSummary.setAmtTax(platformSettleItemList.stream().mapToDouble(platformSettleItem -> platformSettleItem.getInvoiceItem().getAmtTax()).sum());
            //金额
            platformSettleItemSummary.setAmount(platformSettleItemList.stream().mapToDouble(PlatformSettleItem::getAmount).sum());
            //折扣金额
            platformSettleItemSummary.setDiscountAmount(platformSettleItemList.stream().mapToDouble(PlatformSettleItem::getDiscountAmount).sum());
            //实结金额
            Double actualSettlementAmount = platformSettleItemList.stream().mapToDouble(platformSettleItem -> platformSettleItem.getFloorPrice() * platformSettleItem.getActualQty()).sum();
            platformSettleItemSummary.setActualSettlementAmount(actualSettlementAmount);
            //实结单价
            if(actualQty != 0) platformSettleItemSummary.setActualPriceUnit(Arith.round(actualSettlementAmount / actualQty,2));
            //税率
            Double tax = platformSettleItems.get(0).getTax().obtainPercentTypeTax();
            platformSettleItemSummary.setTax(platformSettleItems.get(0).getTax());
            //实结税金
            platformSettleItemSummary.setActualAmtTax(Arith.round(actualSettlementAmount - actualSettlementAmount / (1+ tax),2));
            platformSettleItemSummaryList.add(platformSettleItemSummary);
        }));
        return platformSettleItemSummaryList;
    }

    public JSONObject query(SimpleRequest request){
        JSONObject tempJson = request.getJO();
        JSONObject jsonObject = new JSONObject();
        JSONObject conditionModel = tempJson.getJSONObject("conditionModel");
        JSONArray platformSettleItems = conditionModel.getJSONArray("platformSettleItems");
        jsonObject.put("queryItem",platformSettleItems);
        return jsonObject;
    }

    /**
     * 查询供应商对账明细
     * @param request
     * @return
     */
    public Object queryItem(SimpleRequest request) {
        JSONObject tempJson = request.getJO();
        JSONObject data = tempJson.getJSONObject("data");
        List<PlatformSettleItem> platformSettleItems;
        JSONObject conditionModel = data.getJSONObject("conditionModel");
        //两个不同的入口，数组结构不同
        if(conditionModel == null) {
            //明细行点击
            JSONObject node = data.getJSONObject("node");
            //通过商品和单价过滤
            platformSettleItems = data.getJSONArray("platformSettleItems").toJavaList(PlatformSettleItem.class).stream()
                    .filter(platformSettleItem -> node.getJSONObject("product").getString("id").equals(platformSettleItem.getProduct().getId()) && node.getDoubleValue("priceUnit") == platformSettleItem.getPriceUnit())
                    .collect(Collectors.toList());
        } else {
            //点击货款金额
            platformSettleItems = conditionModel.getJSONArray("platformSettleItems").toJavaList(PlatformSettleItem.class);
        }
        PageImpl<PlatformSettleItem> settleItemPage = pageInfo(tempJson,platformSettleItems,new Sort(Sort.Direction.ASC, "id"));
        List<Map<String, Object>> list = new ArrayList<>();
        //重新拼接抽屉所需数据
        settleItemPage.getContent().forEach(platformSettleItem ->{
            Map<String, Object> map = new HashMap<>();
            InvoiceItem invoiceItem = invoiceItemRepository.findOne(platformSettleItem.getInvoiceItem().getId());
            //账单日期
            map.put("STATEMENT_DATE",DateUtil.format(invoiceItem.getInvoice().getThirdTime(), DateUtil.SHOW_DATE_FORMAT));
            //账单号
            map.put("ID",invoiceItem.getInvoice().getId());
            //账单明细号0
            map.put("ITEM_ID",invoiceItem.getId());
            //商品
            map.put("PRODUCT_NAME","[" + platformSettleItem.getProduct().getId() + "]" + platformSettleItem.getProduct().getName());
            //品类
            map.put("CLASSIFY_NAME",SpringManager.getBean(ProductRepository.class).findOne(platformSettleItem.getProduct().getId()).getClassify().getName());
            //单价
            map.put("PRICE_UNIT",platformSettleItem.getPriceUnit());
            //数量
            map.put("ACTUAL_QTY",platformSettleItem.getActualQty());
            //金额
            map.put("AMOUNT",platformSettleItem.getAmount());
            //税率
            map.put("TAX",platformSettleItem.getTax().getName());
            //税金
            map.put("AMT_TAX",platformSettleItem.getInvoiceItem().getAmtTax());
            //折扣金额
            map.put("DISCOUNT_AMOUNT",platformSettleItem.getDiscountAmount());
            //实结单价
            map.put("FLOOR_PRICE",platformSettleItem.getFloorPrice());
            String customerExpand = invoiceItem.getInvoice().getCustomerExpand();
            if(customerExpand != null){
                FnCustomerExpand fnCustomerExpand = fnCustomerExpandRepository.findOne(customerExpand);
                //车牌
                map.put("CAR_LICENSE",fnCustomerExpand.getCarLicense());
            }
            //源单据
            BusinessType businessType = businessTypeRepository.findOne(platformSettleItem.getOriginBusinessType());
            if(businessType == null){
                map.put("ORIGIN_BUSINESS_TYPE",platformSettleItem.getOriginBusinessType());
            } else {
                map.put("ORIGIN_BUSINESS_TYPE",businessType.getName());
            }
            //源单号
            map.put("ORIGIN",platformSettleItem.getOrigin());
            //第三方单据
            map.put("THIRD_ID",invoiceItem.getInvoice().getThirdId());
            //业务公司
            map.put("COMPANY_NAME","["+platformSettleItem.getCompany().getId() +"]"+ platformSettleItem.getCompany().getName());
            list.add(map);
        });
        //底部汇总数据footer
        JSONArray footer = new JSONArray();
        JSONObject price = new JSONObject();
        price.put("PRICE_UNIT",platformSettleItems.stream().mapToDouble(PlatformSettleItem::getPriceUnit).sum());
        price.put("ACTUAL_QTY",platformSettleItems.stream().mapToDouble(PlatformSettleItem::getActualQty).sum());
        price.put("AMOUNT",platformSettleItems.stream().mapToDouble(PlatformSettleItem::getAmount).sum());
        price.put("AMT_TAX",platformSettleItems.stream().mapToDouble(platformSettleItem -> platformSettleItem.getInvoiceItem().getAmtTax()).sum());
        price.put("DISCOUNT_AMOUNT",platformSettleItems.stream().mapToDouble(PlatformSettleItem::getDiscountAmount).sum());
        price.put("FLOOR_PRICE",platformSettleItems.stream().mapToDouble(PlatformSettleItem::getFloorPrice).sum());
        footer.add(price);
        return MapUtil.mapper("content",list,"footer",footer,"total",settleItemPage.getTotalElements(),
                "page",tempJson.getInteger("page"),"size",tempJson.getInteger("size"),"pages",settleItemPage.getTotalPages());
    }

    /**
     * 手动分页
     * @param jo
     * @param cross
     * @param sort
     * @return
     */
    public PageImpl pageInfo(JSONObject jo, List cross,Sort sort){
        int page = ((Integer) jo.get("page") -1);
        int size =  page * (Integer) jo.get("size");
        List result = new ArrayList<>();
        for (int i = size+1; i <= size+(Integer) jo.get("size"); i++) {
            if (cross.size()>=i)result.add(cross.get(i-1));
        }
        Pageable pageable = PageRequest.of(page, (Integer) jo.get("size"),sort);
        return new PageImpl(result, pageable, cross.size());
    }

    public Map findIncomeItem(SimpleRequest request){
        //查询条件
        List<Map> conditions = request.get("condition");
        List<Map> conditionList = new ArrayList<>();
        //model数据
        JSONObject conditionModel = request.get("conditionModel");
        //修改业务期起止查询条件
        List<Object> arrayList = new ArrayList<>();
        conditions.forEach(condition ->{
            if("incomeItems.startDate".equals(condition.get("field"))){
                condition.put("operator","GTE");
            } else if("incomeItems.endDate".equals(condition.get("field"))){
                condition.put("operator","LTE");
            }
            if("type".equals(condition.get("field"))){
                if ("rebate".equals(condition.get("value"))){
                    arrayList.add("rebate");

                } else if("cost".equals(condition.get("value"))){
                    arrayList.add("cost");
                    arrayList.add("margin");
                    arrayList.add("002366");
                    arrayList.add("002365");
                }
            } else {
                conditionList.add(condition);
            }
        });
        if(!arrayList.isEmpty())
            conditionList.add(MapUtil.mapper("field","inComeCategory.id","operator","IN","value",arrayList));
        //默认查询收入单条件
        conditionList.add(MapUtil.mapper("field","company.id","operator","EQ","value",conditionModel.getJSONObject("company").getString("id")));
        conditionList.add(MapUtil.mapper("field","partner.id","operator","EQ","value",conditionModel.getJSONObject("supplier").getString("id")));
        conditionList.add(MapUtil.mapper("field","incomeItems.done","operator","EQ","value",false));
        conditionList.add(MapUtil.mapper("field","state","operator","EQ","value","approve"));
        List<Income> incomeList = incomeRepository.findAll(JpaDsl.toCriteria(conditionList)).stream().distinct().collect(Collectors.toList());
        List<Map<String, Object>> list = new ArrayList<>();
        incomeList.forEach(income -> income.getIncomeItems().stream().filter(incomeItem -> !incomeItem.isDone() &&
                incomeItem.getIncomeAmount() - incomeItem.getFreezeAmount() - incomeItem.getRecoveryAmount() != 0).forEach(incomeItem -> {
            Map<String, Object> map = new HashMap<>();
            //收入单号
            map.put("incomeId",income.getId());
            map.put("incomeItemId",income.getId() + "-" + incomeItem.getId());
            map.put("incomeItem",incomeItem);
            //收入类别
            map.put("inComeCategory",income.getInComeCategory());
            //收入类型
            map.put("incomeType",incomeItem.getIncomeType());
            //收入金额
            map.put("incomeAmount",incomeItem.getIncomeAmount());
            //冻结金额
            map.put("freezeAmount",incomeItem.getFreezeAmount());
            //已收款金额
            map.put("recoveryAmount",incomeItem.getRecoveryAmount());
            //本地抵扣金额
            map.put("actualAmount",incomeItem.getIncomeAmount() - (incomeItem.getFreezeAmount() + incomeItem.getRecoveryAmount()));
            //已结算金额
            map.put("settleAmount",incomeItem.getFreezeAmount() + incomeItem.getRecoveryAmount());
            //业务期起
            if(incomeItem.getStartDate() != null)
                map.put("reconcileBeginDate",DateUtil.format(incomeItem.getStartDate(), DateUtil.SHOW_DATE_FORMAT));
            //业务期止
            if(incomeItem.getEndDate() != null)
                map.put("reconcileEndDate", DateUtil.format(incomeItem.getEndDate(),DateUtil.SHOW_DATE_FORMAT));
            //计算日期
            if(income.getApproveDate() != null)
                map.put("countDate",DateUtil.format(income.getApproveDate(),DateUtil.SHOW_DATE_FORMAT));
            //备注
            map.put("note",incomeItem.getNote());
            //源单号
            map.put("origin",income.getOrigin());
            list.add(map);
        }));
        Page paged = paged(list, request.get("page"), request.get("size"), null);
        return MapUtil.mapper("content", paged.getContent(), "total", paged.getTotalElements(), "pages", paged.getTotalPages(), "page", request.get("page"));
    }

    public PlatformSettle settle(SimpleRequest request) {
        Object data = request.getData();
        if(((HashMap) ((ArrayList) data).get(0)).get("id") ==null) return null;
        PlatformSettle platformSettle = platformSettleRepository.getOne(((HashMap) ((ArrayList) data).get(0)).get("id").toString());
        platformSettle.setState(((HashMap) ((ArrayList) data).get(1)).get("state").toString());
        return platformSettleRepository.saveAndFlush(platformSettle);
    }

    /**
     * 税票登记获取对账单信息
     * @param request
     * @return
     */
    public JSONObject taxBillQuery(SimpleRequest request){
        JSONObject jo = request.getJO();
        JSONArray conditions = jo.getJSONArray("condition");
        if (CollectionUtils.isEmpty(conditions)){
            conditions = new JSONArray();
        }
        if (StringUtil.isNotEmpty(jo.getString("key"))){
            JSONObject key = new JSONObject();
            key.put("field","platformSettleId");
            key.put("value",jo.getString("key"));
            conditions.add(key);
        }
        JSONObject param = new JSONObject();
        for (Object item : conditions) {
            JSONObject condition = (JSONObject) item;
            String field = condition.getString("field");
            String value = condition.getString("value");
            if (condition.containsKey("type") && condition.getString("type").equals("date")) {
                String operator = condition.getString("operator");
                param.put(field + operator, value);
            }
            param.put(field, value);
        }
        // 查询并分页
        Pageable pageable = PageRequest.of(request.get("page"), request.get("size"));
        int min = pageable.getPageSize() * pageable.getPageNumber();
        int max = pageable.getPageSize() * (pageable.getPageNumber() + 1);
        param.put("min", min);
        param.put("max", max);
        // 查询数据
        JSONArray allJA = platformSettleDao.taxBillQuery(param);
        JSONArray countJA = platformSettleDao.taxBillQueryCount(param);
        Integer count = countJA.getJSONObject(0).getInteger("COUNT");
        JSONObject result = new JSONObject();
        result.put("content", allJA);
        result.put("total", count);
        result.put("pages", count);
        return result;
    }

    /**
     * 更新供应商对账单已登记发票金额及状态
     * @param request
     */
    public void updateInvoicedAmount(SimpleRequest request){
        JSONObject requestJO = request.getJO();
        String id = requestJO.getString("id");
        double amountSum = requestJO.getDoubleValue("amountSum");
        PlatformSettle platformSettle = platformSettleRepository.findOne(id);
        if (ObjectUtils.isEmpty(platformSettle)) return;
        platformSettle.setInvoicedAmount(amountSum);
        if (amountSum == platformSettle.getPayableAmt()){
            platformSettle.setState("already");
        }else {
            platformSettle.setState("section");
        }
        platformSettleRepository.saveAndFlush(platformSettle);
    }
}
